home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 7
/
Amiga Format AFCD07 (Dec 1996, Issue 91).iso
/
serious
/
shareware
/
programming
/
aros
/
dos
/
createnewproc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-13
|
8KB
|
279 lines
/*
(C) 1995-96 AROS - The Amiga Replacement OS
$Id: createnewproc.c,v 1.5 1996/09/13 17:50:05 digulla Exp $
$Log: createnewproc.c,v $
Revision 1.5 1996/09/13 17:50:05 digulla
Use IPTR
Revision 1.4 1996/09/11 12:56:39 digulla
Bugfix and a lot of new checks by M. Fleischer
Desc:
Lang: english
*/
#include <exec/memory.h>
#include <clib/exec_protos.h>
#include <dos/dosextens.h>
#include <dos/filesystem.h>
#include <dos/dostags.h>
#include <clib/dos_protos.h>
#include <utility/tagitem.h>
#include <clib/utility_protos.h>
#include "dos_intern.h"
#define NEWLIST(l) \
((l)->lh_Head=(struct Node *)&(l)->lh_Tail, \
(l)->lh_Tail=NULL, \
(l)->lh_TailPred=(struct Node *)(l))
static void KillCurrentProcess(void);
struct Process *AddProcess(struct Process *process, STRPTR argPtr,
ULONG argSize, APTR initialPC, APTR finalPC, struct DosLibrary *DOSBase);
/*****************************************************************************
NAME */
#include <clib/dos_protos.h>
__AROS_LH1(struct Process *, CreateNewProc,
/* SYNOPSIS */
__AROS_LHA(struct TagItem *, tags, D1),
/* LOCATION */
struct DosLibrary *, DOSBase, 83, Dos)
/* FUNCTION
Create a new process using the tagitem array.
INPUTS
tags - information on the new process.
RESULT
Pointer to the new process or NULL on error.
NOTES
EXAMPLE
BUGS
SEE ALSO
INTERNALS
HISTORY
29-10-95 digulla automatically created from
dos_lib.fd and clib/dos_protos.h
*****************************************************************************/
{
__AROS_FUNC_INIT
__AROS_BASE_EXT_DECL(struct DosLibrary *,DOSBase)
/* Allocated resources */
struct Process *process=NULL;
BPTR input=0, output=0, curdir=0;
STRPTR stack=NULL, name=NULL, argptr=NULL;
ULONG namesize, argsize=0;
struct MemList *memlist=NULL;
struct CommandLineInterface *cli=NULL;
struct Process *me=(struct Process *)FindTask(NULL);
STRPTR s;
BPTR *oldpath, *newpath, *nextpath;
struct TagItem defaults[]=
{
{ NP_Seglist, 0 },
{ NP_Entry, (IPTR)NULL },
{ NP_Input, ~0ul },
{ NP_CloseInput, 1 },
{ NP_Output, ~0ul },
{ NP_CloseOutput, 1 },
{ NP_Error, 0 },
{ NP_CloseError, 1 },
{ NP_CurrentDir, ~0ul },
{ NP_StackSize, 4000 },
{ NP_Name, (IPTR)"New Process" },
{ NP_Priority, me->pr_Task.tc_Node.ln_Pri },
{ NP_Arguments, (IPTR)NULL },
{ NP_Cli, 0 },
{ TAG_END, 0 }
};
/* C has no exceptions. This is a simple replacement. */
#define ERROR_IF(a) if(a) goto error /* Throw a generic error. */
#define ENOMEM_IF(a) if(a) goto enomem /* Throw out of memory. */
ApplyTagChanges(defaults,tags);
process=(struct Process *)AllocMem(sizeof(struct Process),MEMF_PUBLIC|MEMF_CLEAR);
ENOMEM_IF(process==NULL);
stack=AllocMem(defaults[9].ti_Data,MEMF_PUBLIC);
ENOMEM_IF(stack==NULL);
s=(STRPTR)defaults[10].ti_Data;
while(*s++)
;
namesize=s-(STRPTR)defaults[10].ti_Data;
name=AllocMem(namesize,MEMF_PUBLIC);
ENOMEM_IF(name==NULL);
s=(STRPTR)defaults[12].ti_Data;
if(s!=NULL)
{
while(*s++)
;
argsize=s-(STRPTR)defaults[12].ti_Data;
argptr=(STRPTR)AllocVec(argsize,MEMF_PUBLIC);
ENOMEM_IF(argptr==NULL);
}
memlist=AllocMem(sizeof(struct MemList)+2*sizeof(struct MemEntry),MEMF_ANY);
ENOMEM_IF(memlist==NULL);
if(defaults[13].ti_Data)
{
cli=(struct CommandLineInterface *)AllocDosObject(DOS_CLI,NULL);
ENOMEM_IF(cli==NULL);
oldpath=NULL;
if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
{
struct CommandLineInterface *oldcli=Cli();
if(oldcli!=NULL)
oldpath=BADDR(oldcli->cli_CommandDir);
}
newpath=&cli->cli_CommandDir;
while(oldpath!=NULL)
{
nextpath=AllocVec(2*sizeof(BPTR),MEMF_CLEAR);
ENOMEM_IF(nextpath==NULL);
newpath[0]=MKBADDR(nextpath);
nextpath[1]=DupLock(oldpath[1]);
ERROR_IF(!nextpath[1]);
newpath=nextpath;
oldpath=BADDR(oldpath[0]);
}
}
if(defaults[2].ti_Data==~0ul)
{
input=Open("NIL:",MODE_OLDFILE);
ERROR_IF(!input);
defaults[2].ti_Data=input;
}
if(defaults[4].ti_Data==~0ul)
{
output=Open("NIL:",MODE_NEWFILE);
ERROR_IF(!output);
defaults[4].ti_Data=output;
}
if(defaults[8].ti_Data==~0ul)
{
if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
{
curdir=Lock("",SHARED_LOCK);
ERROR_IF(!curdir);
defaults[8].ti_Data=curdir;
}else
defaults[8].ti_Data=0;
}
CopyMem((APTR)defaults[10].ti_Data,name,namesize);
CopyMem((APTR)defaults[12].ti_Data,argptr,argsize);
process->pr_Task.tc_Node.ln_Type=NT_PROCESS;
process->pr_Task.tc_Node.ln_Name=name;
process->pr_Task.tc_Node.ln_Pri=defaults[11].ti_Data;
process->pr_Task.tc_SPLower=stack;
process->pr_Task.tc_SPUpper=stack+defaults[9].ti_Data;
/* process->pr_ReturnAddr; */
NEWLIST(&process->pr_Task.tc_MemEntry);
memlist->ml_NumEntries=3;
memlist->ml_ME[0].me_Addr=process;
memlist->ml_ME[0].me_Length=sizeof(struct Process);
memlist->ml_ME[1].me_Addr=stack;
memlist->ml_ME[1].me_Length=defaults[9].ti_Data;
memlist->ml_ME[2].me_Addr=name;
memlist->ml_ME[2].me_Length=namesize;
AddHead(&process->pr_Task.tc_MemEntry,&memlist->ml_Node);
process->pr_MsgPort.mp_Node.ln_Type=NT_MSGPORT;
process->pr_MsgPort.mp_Flags=PA_SIGNAL;
process->pr_MsgPort.mp_SigBit=SIGB_DOS;
process->pr_MsgPort.mp_SigTask=process;
NEWLIST(&process->pr_MsgPort.mp_MsgList);
process->pr_SegList=defaults[0].ti_Data;
process->pr_StackSize=defaults[9].ti_Data;
process->pr_GlobVec=NULL;
Forbid();
process->pr_TaskNum=DOSBase->dl_ProcCnt++;
Permit();
process->pr_StackBase=(IPTR)process->pr_Task.tc_SPUpper;
process->pr_Result2=0;
process->pr_CurrentDir=defaults[8].ti_Data;
process->pr_CIS=defaults[2].ti_Data;
process->pr_COS=defaults[4].ti_Data;
process->pr_CES=defaults[6].ti_Data;
/* process->pr_ConsoleTask=; */
/* process->pr_FileSystemTask=; */
process->pr_CLI=MKBADDR(cli);
/* process->pr_PktWait=; */
/* process->pr_WindowPtr=; */
/* process->pr_HomeDir=; */
process->pr_Flags=(defaults[3].ti_Data?PRF_CLOSEINPUT:0)|
(defaults[5].ti_Data?PRF_CLOSEOUTPUT:0)|
(defaults[7].ti_Data?PRF_CLOSEERROR:0)|
(defaults[13].ti_Data?PRF_FREECLI:0)|
PRF_FREEARGS|PRF_FREESEGLIST|PRF_FREECURRDIR;
/* process->pr_ExitCode=; */
/* process->pr_ExitData=; */
process->pr_Arguments=argptr;
NEWLIST((struct List *)&process->pr_LocalVars);
process->pr_ShellPrivate=0;
if(AddProcess(process,argptr,argsize,defaults[0].ti_Data?
(APTR)BADDR(defaults[0].ti_Data+1):
(APTR)defaults[1].ti_Data,KillCurrentProcess,
DOSBase)!=NULL)
return process;
/* Fall through */
enomem:
if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
me->pr_Result2=ERROR_NO_FREE_STORE;
error:
FreeDosObject(DOS_CLI,cli);
UnLock(curdir);
Close(output);
Close(input);
FreeVec(argptr);
if(memlist!=NULL)
FreeMem(memlist,sizeof(struct MemList)+2*sizeof(struct MemEntry));
if(name!=NULL)
FreeMem(name,namesize);
if(stack!=NULL)
FreeMem(stack,defaults[9].ti_Data);
if(process!=NULL)
FreeMem(process,sizeof(struct Process));
return NULL;
__AROS_FUNC_EXIT
} /* CreateNewProc */
static void KillCurrentProcess(void)
{
/* I need the global here because there is no local way to get it */
extern struct DosLibrary *DOSBase;
struct Process *me=(struct Process *)FindTask(NULL);
if(me->pr_Flags&PRF_CLOSEINPUT)
Close(me->pr_CIS);
if(me->pr_Flags&PRF_CLOSEOUTPUT)
Close(me->pr_COS);
if(me->pr_Flags&PRF_CLOSEERROR)
Close(me->pr_CES);
if(me->pr_Flags&PRF_FREEARGS)
FreeVec(me->pr_Arguments);
if(me->pr_Flags&PRF_FREESEGLIST)
UnLoadSeg(me->pr_SegList);
if(me->pr_Flags&PRF_FREECURRDIR)
UnLock(me->pr_CurrentDir);
if(me->pr_Flags&PRF_FREECLI)
FreeDosObject(DOS_CLI,BADDR(me->pr_CLI));
RemTask(NULL);
}